package com.gzs.learn.payment.service.impl;

import com.gzs.learn.inf.BaseResponseDto;
import com.gzs.learn.inf.split.SplitIdUtil;
import com.gzs.learn.payment.clients.ISerialQueryClient;
import com.gzs.learn.payment.inf.dto.UnifyPayment;
import com.gzs.learn.payment.inf.dto.UnifyPaymentResponse;
import com.gzs.learn.payment.inf.dto.UnifyRefund;
import com.gzs.learn.payment.inf.dto.UnifyRefundResponse;
import com.gzs.learn.payment.inf.enums.PaymentResponseCodeEnum;
import com.gzs.learn.payment.inf.enums.PaymentStatusEnum;
import com.gzs.learn.payment.inf.exception.PaymentException;
import com.gzs.learn.payment.mapper.*;
import com.gzs.learn.payment.model.po.*;
import com.gzs.learn.payment.service.IPaymentService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

import static com.gzs.learn.payment.PaymentConstants.SERIAL_PAYMENT;
import static com.gzs.learn.payment.PaymentConstants.SERIAL_PAYMENT_REFUND;

/**
 * @author zhisong.guan
 */
@Service
@Transactional
@RequiredArgsConstructor
public class PaymentServiceImpl implements IPaymentService {

    private final ISerialQueryClient serialQueryClient;

    private final PaymentMapper paymentMapper;


    private final PaymentRefundMapper paymentRefundMapper;


    private final PaySuccessMapper paySuccessMapper;


    private final PaySuccessWechatMapper paySuccessWechatMapper;


    private final PaySuccessWechatPromotionMapper paySuccessWechatPromotionMapper;


    private final PaySuccessAlipayMapper paySuccessAlipayMapper;


    private final PaySuccessUnionPayMapper paySuccessUnionPayMapper;

    @Override
    public BaseResponseDto<UnifyPaymentResponse> unifyPayment(UnifyPayment unifyPayment) {
        BaseResponseDto<Long> serialResp = serialQueryClient.getSegmentId(SERIAL_PAYMENT);
        if (!BaseResponseDto.isSuccess(serialResp)) {
            throw new PaymentException(PaymentResponseCodeEnum.SERIAL_ERROR);
        }
        String paymentStatus = PaymentStatusEnum.N.getCode();
        Payment payment = new Payment();
        long orderId = unifyPayment.getOrderId();
        // 计算serial
        long serial = SplitIdUtil.calcNewId(serialResp.getData(), orderId);

        payment.setSerial(serial);
        payment.setMemberId(unifyPayment.getMemberId());
        payment.setOrderId(orderId);
        payment.setOrderFrom(unifyPayment.getOrderFrom());
        payment.setAmt(unifyPayment.getAmt());
        payment.setCreateTime(new Date());
        payment.setOperatorIp("");
        payment.setChannel(unifyPayment.getChannel());
        payment.setClientName("");
        payment.setOperator(unifyPayment.getOperator());
        payment.setStatus(paymentStatus);
        paymentMapper.insert(payment);
        UnifyPaymentResponse paymentResponse = new UnifyPaymentResponse();
        paymentResponse.setPaymentStatus(paymentStatus);
        paymentResponse.setSerial(serial);
        return BaseResponseDto.success(paymentResponse);
    }

    @Override
    public BaseResponseDto<UnifyRefundResponse> unifyRefund(UnifyRefund unifyRefund) {
        BaseResponseDto<Long> serialResp = serialQueryClient.getSegmentId(SERIAL_PAYMENT_REFUND);
        if (!BaseResponseDto.isSuccess(serialResp)) {
            throw new PaymentException(PaymentResponseCodeEnum.SERIAL_ERROR);
        }
        Payment payment = paymentMapper.selectById(unifyRefund.getSerial());
        if (payment == null) {
            return BaseResponseDto.bizError("未找到指定支付流水号的支付记录");
        }
        String paymentStatus = PaymentStatusEnum.N.getCode();
        PaymentRefund paymentRefund = new PaymentRefund();
        long orderId = unifyRefund.getOrderId();
        // 计算serial
        long refundSerial = SplitIdUtil.calcNewId(serialResp.getData(), orderId);

        paymentRefund.setRefundSerial(refundSerial);
        paymentRefund.setSerial(payment.getSerial());
        paymentRefund.setMemberId(payment.getMemberId());
        paymentRefund.setOrderId(orderId);
        paymentRefund.setOrderFrom(payment.getOrderFrom());
        paymentRefund.setAmt(unifyRefund.getRefundAmt());
        paymentRefund.setCreateTime(new Date());
        paymentRefund.setOperatorIp("");
        paymentRefund.setClientName("");
        paymentRefund.setOperator(unifyRefund.getOperator());
        paymentRefund.setStatus(paymentStatus);
        paymentRefundMapper.insert(paymentRefund);
        UnifyRefundResponse unifyRefundResponse = new UnifyRefundResponse();
        unifyRefundResponse.setRefundSerial(refundSerial);
        unifyRefundResponse.setPaymentStatus(PaymentStatusEnum.R0.toString());
        return BaseResponseDto.success(unifyRefundResponse);
    }

    @Override
    public BaseResponseDto<?> callback(PaySuccess paySuccess, PaySuccessWechat paySuccessWechat) {
        PaySuccess existPaySuccess = paySuccessMapper.selectById(paySuccess.getSerial());
        if (existPaySuccess != null) {
            return BaseResponseDto.success("已经发起过回调,无需处理");
        }
        baseSuccess(paySuccess);
        paySuccessWechatMapper.insert(paySuccessWechat);
        for (PaySuccessWechatPromotion promotion : paySuccessWechat.getPromotions()) {
            paySuccessWechatPromotionMapper.insert(promotion);
        }
        return BaseResponseDto.success("处理成功");
    }

    @Override
    public BaseResponseDto<?> callback(PaySuccess paySuccess, PaySuccessAlipay paySuccessAlipay) {
        PaySuccess existPaySuccess = paySuccessMapper.selectById(paySuccess.getSerial());
        if (existPaySuccess != null) {
            return BaseResponseDto.success("已经发起过回调,无需处理");
        }
        baseSuccess(paySuccess);
        paySuccessAlipayMapper.insert(paySuccessAlipay);
        return BaseResponseDto.success("处理成功");
    }

    @Override
    public BaseResponseDto<?> callback(PaySuccess paySuccess, PaySuccessUnionPay paySuccessUnionPay) {
        PaySuccess existPaySuccess = paySuccessMapper.selectById(paySuccess.getSerial());
        if (existPaySuccess != null) {
            return BaseResponseDto.success("已经发起过回调,无需处理");
        }
        baseSuccess(paySuccess);
        paySuccessUnionPayMapper.insert(paySuccessUnionPay);
        return BaseResponseDto.success("处理成功");
    }

    /**
     * 公共的回调成功方法
     */
    private void baseSuccess(PaySuccess paySuccess) {
        Payment payment = new Payment();
        payment.setSerial(paySuccess.getSerial());
        payment.setStatus(PaymentStatusEnum.S.getCode());
        paymentMapper.updateById(payment);
        paySuccessMapper.insert(paySuccess);
    }
}
